package principal;

import java.awt.Color;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

public class Tetramino implements Serializable{

	private static final long serialVersionUID = 3L;
	protected int orientacao;
	protected int tipo;
	protected boolean estado;
	protected Quadrado quadradoReferencia;
	protected boolean isDaVez;
	protected List<Quadrado> quadrados;
	protected MatrizDeQuadrados matriz;
	protected Jogador jogador;

	public Tetramino(Quadrado quadradoReferencia, MatrizDeQuadrados matriz, Jogador jog) {
		this.quadradoReferencia = quadradoReferencia;
		this.matriz = matriz;
		this.jogador = jog;
		gerarAleatorio();
	}

	public void redesenharQuadrados(Quadrado quadradoReferencia, int orientacao) {
		this.quadrados = gerarReferencias(quadradoReferencia, orientacao);
		this.orientacao = orientacao;
		
		quadradoReferencia.setOcupado(true);
		this.matriz.getArea()[(int) quadradoReferencia.getReferencia().getX()][(int) quadradoReferencia.getReferencia().getY()].defineCor(this.getColor(jogador.getCor()));
		this.matriz.getArea()[(int) quadradoReferencia.getReferencia().getX()][(int) quadradoReferencia.getReferencia().getY()].setOcupado(true);
		this.matriz.getArea()[(int) quadradoReferencia.getReferencia().getX()][(int) quadradoReferencia.getReferencia().getY()].setJogador(jogador);
		this.matriz.getArea()[(int) quadradoReferencia.getReferencia().getX()][(int) quadradoReferencia.getReferencia().getY()].repaint();
		this.matriz.getArea()[(int) quadradoReferencia.getReferencia().getX()][(int) quadradoReferencia.getReferencia().getY()].validate();
		
//		quadradoReferencia.setBackground(Tetris.getInstance().getColor(jogador.getCor()));
//		quadradoReferencia.setOcupado(true);
//		quadradoReferencia.setJogador(jogador);
//		quadradoReferencia.repaint();
//		quadradoReferencia.validate();

		for(Quadrado quadrado : quadrados){
			quadrado.setOcupado(true);
			this.matriz.getArea()[(int) quadrado.getReferencia().getX()][(int) quadrado.getReferencia().getY()].defineCor(this.getColor(jogador.getCor()));
			this.matriz.getArea()[(int) quadrado.getReferencia().getX()][(int) quadrado.getReferencia().getY()].setOcupado(true);
			this.matriz.getArea()[(int) quadrado.getReferencia().getX()][(int) quadrado.getReferencia().getY()].setJogador(jogador);
			this.matriz.getArea()[(int) quadrado.getReferencia().getX()][(int) quadrado.getReferencia().getY()].repaint();
			this.matriz.getArea()[(int) quadrado.getReferencia().getX()][(int) quadrado.getReferencia().getY()].validate();
			
			
//			quadrado.setBackground();
//			quadrado.setOcupado(true);
//			quadrado.setJogador(jogadcor); 
//			quadrado.repaint();
//			quadrado.validate();
		}
		
		
//		tetris.getTabuleiro().repaint();
//		tetris.getTabuleiro().validate();
//		
//		tetris.getPreview().repaint();
//		tetris.getPreview().validate();
		
	}

	public void girar() {
		int orient = orientacao;
		orient--;
		if(orient < 0){
			orient = 3;
		}
		
		this.matriz.getArea()[(int) quadradoReferencia.getReferencia().getX()][(int) quadradoReferencia.getReferencia().getY()].setOcupado(false);
		if(((Tabuleiro)matriz).verificaSePosicaoEhValida(quadradoReferencia, this, orient)){
			redesenharQuadrados(quadradoReferencia, orient);
		} else{
			this.matriz.getArea()[(int) quadradoReferencia.getReferencia().getX()][(int) quadradoReferencia.getReferencia().getY()].setOcupado(true);
		}
	}
	
	//colocar no diagrama
	public void deslocarParaDireita() {
		int x = (int)quadradoReferencia.getReferencia().getX();
		int y = (int)quadradoReferencia.getReferencia().getY();
		Quadrado quadrado = matriz.getQuadrado(x, y+1);
		
		this.matriz.getArea()[(int) quadradoReferencia.getReferencia().getX()][(int) quadradoReferencia.getReferencia().getY()].setOcupado(false);
		if(((Tabuleiro)matriz).verificaSePosicaoEhValida(quadrado, this, orientacao)){
			quadradoReferencia = quadrado;
			redesenharQuadrados(quadradoReferencia, orientacao);
		} else{
			this.matriz.getArea()[(int) quadradoReferencia.getReferencia().getX()][(int) quadradoReferencia.getReferencia().getY()].setOcupado(true);
		}
	}
	
	//colocar no diagrama
	public void deslocarParaEsquerda(){
		int x = (int)quadradoReferencia.getReferencia().getX();
		int y = (int)quadradoReferencia.getReferencia().getY();
		Quadrado quadrado = matriz.getQuadrado(x, y-1);
		
		this.matriz.getArea()[(int) quadradoReferencia.getReferencia().getX()][(int) quadradoReferencia.getReferencia().getY()].setOcupado(false);
		if(((Tabuleiro)matriz).verificaSePosicaoEhValida(quadrado, this, orientacao)){
			quadradoReferencia = quadrado;
			redesenharQuadrados(quadradoReferencia, orientacao);
		} else{
			this.matriz.getArea()[(int) quadradoReferencia.getReferencia().getX()][(int) quadradoReferencia.getReferencia().getY()].setOcupado(true);
		}
	}
	
	public boolean acelerarQueda() {
		boolean emQueda = true;
		int x = (int)quadradoReferencia.getReferencia().getX();
		int y = (int)quadradoReferencia.getReferencia().getY();
		Quadrado quadrado = matriz.getQuadrado(x+1, y);
		
		quadradoReferencia.setOcupado(false);
		if(((Tabuleiro)matriz).verificaSePosicaoEhValida(quadrado, this, orientacao)){
			quadradoReferencia = quadrado;
			redesenharQuadrados(quadradoReferencia, orientacao);
		} else{
			this.matriz.getArea()[(int) quadradoReferencia.getReferencia().getX()][(int) quadradoReferencia.getReferencia().getY()].defineCor(this.getColor(jogador.getCor()));
			this.matriz.getArea()[(int) quadradoReferencia.getReferencia().getX()][(int) quadradoReferencia.getReferencia().getY()].setOcupado(true);
			this.matriz.getArea()[(int) quadradoReferencia.getReferencia().getX()][(int) quadradoReferencia.getReferencia().getY()].setJogador(jogador);
			
			
//			quadradoReferencia.setOcupado(true);
//			quadradoReferencia.defineCor(Tetris.getInstance().getColor(jogador.getCor()));
//			quadradoReferencia.setJogador(jogador); 
			
			emQueda = false;
		}

		return emQueda;
	}
	
	//colocar no diagrama
	public void apagarAntigos(){
		if(quadrados != null){
			for(Quadrado quadrado : quadrados){
				quadrado.setOcupado(false);
				quadrado.setBackground(Color.WHITE);
				quadrado.repaint();
				quadrado.validate();
				
				
				this.matriz.getArea()[(int) quadrado.getReferencia().getX()][(int) quadrado.getReferencia().getY()].defineCor(Color.WHITE);
				this.matriz.getArea()[(int) quadrado.getReferencia().getX()][(int) quadrado.getReferencia().getY()].setOcupado(false);
				this.matriz.getArea()[(int) quadrado.getReferencia().getX()][(int) quadrado.getReferencia().getY()].setJogador(null);
				this.matriz.getArea()[(int) quadrado.getReferencia().getX()][(int) quadrado.getReferencia().getY()].repaint();
				this.matriz.getArea()[(int) quadrado.getReferencia().getX()][(int) quadrado.getReferencia().getY()].validate();
			}
			
			quadradoReferencia.setOcupado(false);
			this.matriz.getArea()[(int) quadradoReferencia.getReferencia().getX()][(int) quadradoReferencia.getReferencia().getY()].defineCor(Color.WHITE);
			this.matriz.getArea()[(int) quadradoReferencia.getReferencia().getX()][(int) quadradoReferencia.getReferencia().getY()].setOcupado(false);
			this.matriz.getArea()[(int) quadradoReferencia.getReferencia().getX()][(int) quadradoReferencia.getReferencia().getY()].setJogador(null);
			this.matriz.getArea()[(int) quadradoReferencia.getReferencia().getX()][(int) quadradoReferencia.getReferencia().getY()].repaint();
			this.matriz.getArea()[(int) quadradoReferencia.getReferencia().getX()][(int) quadradoReferencia.getReferencia().getY()].validate();
			
//			quadradoReferencia.setBackground(Color.WHITE);
//			quadradoReferencia.setOcupado(false);
//			quadradoReferencia.repaint();
//			quadradoReferencia.validate();
		}
	}
	//colocar no diagrama
	public void gerarAleatorio() {
		Random rn = new Random();
		int randonN = rn.nextInt();
		if(randonN < 0){
			randonN = randonN*(-1);
		}
		int randomNumOrientacao = randonN % 3;
		
		randonN = rn.nextInt();
		if(randonN < 0){
			randonN = randonN*(-1);
		}
		int randomNumtipo = randonN % 7;
		
		this.orientacao = randomNumOrientacao;	
		this.tipo = randomNumtipo;
		
		quadrados = gerarReferencias(quadradoReferencia, orientacao);
		redesenharQuadrados(quadradoReferencia, orientacao);
	}
	
	//colocar no diagrama
	public Quadrado getQuadradoReferencia() {
		return this.quadradoReferencia;
	}
	
	public void setQuadradoReferencia(Quadrado quadradoReferencia) {
		this.quadradoReferencia = quadradoReferencia;
	}
	
	//colocar no diagrama
	public List<Quadrado> gerarReferencias(Quadrado quadrado, int orientacao){
		int x = (int) quadrado.getReferencia().getX();
		int y = (int) quadrado.getReferencia().getY();

		LinkedList<Quadrado> quadrados = new LinkedList<Quadrado>();
		
		switch (tipo) {
		
		case 0:
			if(orientacao == 0){
				quadrados.add(matriz.getQuadrado(x, y+1));
				quadrados.add(matriz.getQuadrado(x, y-1));
				quadrados.add(matriz.getQuadrado(x+1, y));
			} else if(orientacao == 1){
				quadrados.add(matriz.getQuadrado(x+1, y));
				quadrados.add(matriz.getQuadrado(x-1, y));
				quadrados.add(matriz.getQuadrado(x, y+1));
			} else if(orientacao == 2){
				quadrados.add(matriz.getQuadrado(x, y+1));
				quadrados.add(matriz.getQuadrado(x, y-1));
				quadrados.add(matriz.getQuadrado(x-1, y));
			} else if(orientacao == 3){
				quadrados.add(matriz.getQuadrado(x+1, y));
				quadrados.add(matriz.getQuadrado(x-1, y));
				quadrados.add(matriz.getQuadrado(x, y-1));
			}
			break;
		case 1:
			quadrados.add(matriz.getQuadrado(x+1, y));
			quadrados.add(matriz.getQuadrado(x, y+1));
			quadrados.add(matriz.getQuadrado(x+1, y+1));
			break;
		case 2:
			if(orientacao == 0 || orientacao == 2){
				quadrados.add(matriz.getQuadrado(x, y-1));
				quadrados.add(matriz.getQuadrado(x, y+1));
				quadrados.add(matriz.getQuadrado(x, y+2));
			} else if(orientacao == 1 || orientacao == 3){
				quadrados.add(matriz.getQuadrado(x-1, y));
				quadrados.add(matriz.getQuadrado(x+1, y));
				quadrados.add(matriz.getQuadrado(x+2, y));
			}
			break;
		case 3:
			if(orientacao == 0 || orientacao == 2){
				quadrados.add(matriz.getQuadrado(x+1, y));
				quadrados.add(matriz.getQuadrado(x, y-1));
				quadrados.add(matriz.getQuadrado(x-1, y-1));
			} else if(orientacao == 1 || orientacao == 3){
				quadrados.add(matriz.getQuadrado(x, y-1));
				quadrados.add(matriz.getQuadrado(x-1, y));
				quadrados.add(matriz.getQuadrado(x-1, y+1));
			}
			break;
		case 4:
			if(orientacao == 0 || orientacao == 2){
				quadrados.add(matriz.getQuadrado(x-1, y));
				quadrados.add(matriz.getQuadrado(x, y-1));
				quadrados.add(matriz.getQuadrado(x+1, y-1));
			} else if(orientacao == 1 || orientacao == 3){
				quadrados.add(matriz.getQuadrado(x-1, y));
				quadrados.add(matriz.getQuadrado(x, y+1));
				quadrados.add(matriz.getQuadrado(x-1, y-1));
			}
			break;
		case 5:
			if(orientacao == 0){
				quadrados.add(matriz.getQuadrado(x, y-1));
				quadrados.add(matriz.getQuadrado(x, y+1));
				quadrados.add(matriz.getQuadrado(x+1, y-1));
			} else if(orientacao == 1){
				quadrados.add(matriz.getQuadrado(x-1, y));
				quadrados.add(matriz.getQuadrado(x+1, y));
				quadrados.add(matriz.getQuadrado(x+1, y+1));
			} else if(orientacao == 2){
				quadrados.add(matriz.getQuadrado(x, y-1));
				quadrados.add(matriz.getQuadrado(x, y+1));
				quadrados.add(matriz.getQuadrado(x-1, y+1));
			} else if(orientacao == 3){
				quadrados.add(matriz.getQuadrado(x+1, y));
				quadrados.add(matriz.getQuadrado(x-1, y));
				quadrados.add(matriz.getQuadrado(x-1, y-1));
			}
			break;
		case 6:
			if(orientacao == 0){
				quadrados.add(matriz.getQuadrado(x+1, y));
				quadrados.add(matriz.getQuadrado(x-1, y));
				quadrados.add(matriz.getQuadrado(x-1, y+1));
			} else if(orientacao == 1){
				quadrados.add(matriz.getQuadrado(x, y-1));
				quadrados.add(matriz.getQuadrado(x, y+1));
				quadrados.add(matriz.getQuadrado(x-1, y-1));
			} else if(orientacao == 2){
				quadrados.add(matriz.getQuadrado(x+1, y));
				quadrados.add(matriz.getQuadrado(x-1, y));
				quadrados.add(matriz.getQuadrado(x+1, y-1));
			} else if(orientacao == 3){
				quadrados.add(matriz.getQuadrado(x, y-1));
				quadrados.add(matriz.getQuadrado(x, y+1));
				quadrados.add(matriz.getQuadrado(x+1, y+1));
			}
			break;
		}
		
		boolean zerarQuadrados = false;
		for(Quadrado quad : quadrados){
			if(quad.getReferencia().getX() == -1){
				zerarQuadrados = true;
				break;
			}
		}
		
		if(zerarQuadrados){
			quadrados = new LinkedList<Quadrado>();
		}
		
		return quadrados;
	}
	
	public Color getColor(int colorNumber){
		switch (colorNumber) {
		case 0:
			return Color.YELLOW;
		case 1:
			return Color.BLUE;
		case 2:
			return Color.CYAN;
		case 3:
			return Color.GREEN;
		case 4:
			return Color.RED;
		case 5:
			return Color.ORANGE;
		case 6:
			return Color.PINK;
		default:
			return Color.GRAY;
		}
	}
	
	public List<Quadrado> getQuadrados() {
		return quadrados;
	}
	
	public void setMatriz(MatrizDeQuadrados matriz) {
		this.matriz = matriz;
	}
	
	public int getOrientacao() {
		return orientacao;
	}

	public Jogador getJogador() {
		return jogador;
	}

	public void setJogador(Jogador jogador) {
		this.jogador = jogador;
	}
	
	
}